package cn.bonoon.kernel.util;

import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;

import javax.crypto.Cipher;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public final class RSAUtil extends CryptoUtil {
	private static final String RSA = "RSA";
	private static final String algorithm = "MD5withRSA";
	/** 默认的安全服务提供者 */
    private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider();
	public static KeyPair genKeys(String keyInfo) throws Exception {

		KeyPairGenerator keygen = KeyPairGenerator.getInstance(RSA, DEFAULT_PROVIDER);
		SecureRandom random = new SecureRandom();
		random.setSeed(keyInfo.getBytes());
		// 初始加密，长度为512，必须是大于512才可以的
		keygen.initialize(1024, random);
		// 取得密钥对
		KeyPair kp = keygen.generateKeyPair();
		return kp;
		// // 取得公钥
		// PublicKey publicKey = kp.getPublic();
		// System.out.println(publicKey);
		// saveFile(publicKey, "pk.dat");
		// // 取得私钥
		// PrivateKey privateKey = kp.getPrivate();
		// saveFile(privateKey, "sk.dat");
	}

	/**
	 * 加密,key可以是公钥，也可以是私钥
	 * 
	 * @param message
	 * @return
	 * @throws Exception
	 */
	public static byte[] encrypt(String message, Key key) throws Exception {
		return encrypt(message.getBytes(), key);
	}

	public static byte[] encrypt(byte[] input, Key key) throws Exception {
		Cipher cipher = Cipher.getInstance(RSA, DEFAULT_PROVIDER);
		cipher.init(Cipher.ENCRYPT_MODE, key);
		return cipher.doFinal(input);
	}

	/**
	 * 解密，key可以是公钥，也可以是私钥，如果是公钥加密就用私钥解密，反之亦然
	 * 
	 * @param message
	 * @return
	 * @throws Exception
	 */
	public static byte[] decrypt(String message, Key key) throws Exception {
		return decrypt(toBytes(message), key);
	}

	public static byte[] decrypt(byte[] input, Key key) throws Exception {
		Cipher cipher = Cipher.getInstance(RSA, DEFAULT_PROVIDER);
		cipher.init(Cipher.DECRYPT_MODE, key);
		return cipher.doFinal(input);
	}

	/**
	 * 用私钥签名
	 */
	public static byte[] sign(byte[] source, PrivateKey key) throws Exception {
		Signature signetcheck = Signature.getInstance(algorithm);
		signetcheck.initSign(key);
		signetcheck.update(source);
		return signetcheck.sign();
	}

	public static byte[] sign(String message, PrivateKey key) throws Exception {
		return sign(message.getBytes(), key);
	}

	/**
	 * 用公钥验证签名的正确性
	 * 
	 * @param message
	 * @param signStr
	 * @return
	 * @throws Exception
	 */
	public static boolean verifySign(String message, String signStr, PublicKey key)
			throws Exception {
		if (message == null || signStr == null || key == null) {
			return false;
		}
		return verifySign(message.getBytes(), toBytes(signStr), key);
	}

	public static boolean verifySign(byte[] data, byte[] signature, PublicKey key)
			throws Exception {
		Signature signetcheck = Signature.getInstance(algorithm);
		signetcheck.initVerify(key);
		signetcheck.update(data);
		return signetcheck.verify(signature);
	}

//	/**
//	 * 从文件读取object
//	 * 
//	 * @param fileName
//	 * @return
//	 * @throws Exception
//	 */
	// private Object readFromFile(String fileName) throws Exception {
	// ObjectInputStream input = new ObjectInputStream(new FileInputStream(
	// fileName));
	// Object obj = input.readObject();
	// input.close();
	// return obj;
	// }

	// public static String toHexString(byte[] b) {
	// StringBuilder sb = new StringBuilder(b.length * 2);
	// for (int i = 0; i < b.length; i++) {
	// sb.append(HEXCHAR[(b[i] & 0xf0) >>> 4]);
	// sb.append(HEXCHAR[b[i] & 0x0f]);
	// }
	// return sb.toString();
	// }

	// private static char[] HEXCHAR = { '0', '1', '2', '3', '4', '5', '6', '7',
	// '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
}
